﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class RectangleConnTerminalCheck
	{
		public bool BeCorrectOrientation(Duct duct, XYZ globalPoint, IList<FamilyInstance> listTerminal)
		{
			bool result = true;
			List<Connector> connectorAll = YJKRevitTools.GetConnectorAll(duct);
			Connector connector = connectorAll[0];
			Connector connector2 = connectorAll[1];
			if (connectorAll[0].Origin.DistanceTo(globalPoint) > connectorAll[1].Origin.DistanceTo(globalPoint))
			{
				connector = connectorAll[1];
				connector2 = connectorAll[0];
			}
			XYZ origin = connector.Origin;
			XYZ origin2 = connector2.Origin;
			XYZ xyz = origin.Subtract(origin2).Normalize();
			YJKLine hyline = new YJKLine(connector.Origin, connector2.Origin);
			hyline.MakeUnBound();
			foreach (FamilyInstance elem in listTerminal)
			{
				XYZ origin3 = new ConnectHelper().GetYJKElementConnector(elem).Origin;
				XYZ project = hyline.GetProject(origin3);
				XYZ xyz2 = origin.Subtract(project).Normalize();
				double num = origin.DistanceTo(project);
				if (!xyz2.IsAlmostEqualTo(xyz) || num < 0.65616797900262469)
				{
					result = false;
					break;
				}
			}
			return result;
		}

		public int BatchConnCloseTerminal(Duct duct, IList<FamilyInstance> listTerminal)
		{
			string value = "";
			int num = 0;
			HYDuctConnect hyductConnect = new HYDuctConnect();
			foreach (FamilyInstance familyInstance in listTerminal)
			{
				Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, familyInstance);
				if (elementConnector == null || elementConnector.IsConnected)
				{
					num++;
				}
				else
				{
					int connType = -1;
					value = hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref connType, true);
					if (string.IsNullOrEmpty(value))
					{
						hyductConnect.MoveTerminal(duct, familyInstance, connType);
						if (hyductConnect.DuctConnSideTerminalTakeOff(duct, familyInstance, ref value, connType, false))
						{
							num++;
						}
					}
				}
			}
			if (listTerminal.Count <= num)
			{
				return 0;
			}
			return listTerminal.Count - num;
		}

		public bool CheckConnShape(Duct duct, IList<Element> listTerminal)
		{
			bool result = true;
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			foreach (Element elem in listTerminal)
			{
				if (new ConnectHelper().GetYJKElementConnector(elem).Shape != hypiping.Shape)
				{
					result = false;
					break;
				}
			}
			return result;
		}

		public Dictionary<Duct, List<FamilyInstance>> GroupDuctsAndTerminals(IList<Duct> listDuct, IList<FamilyInstance> terminals, ref List<FamilyInstance> notConnTerminals, bool beOnDuct = true)
		{
			new Dictionary<Duct, List<FamilyInstance>>();
			Dictionary<FamilyInstance, List<Duct>> dictionary = new Dictionary<FamilyInstance, List<Duct>>();
			if (beOnDuct)
			{
				dictionary = this.GetListTerminalConnDuct(listDuct, terminals);
			}
			else
			{
				dictionary = this.GetMatchedDuctsAndTerminal(listDuct, terminals);
			}
			if (terminals.Count != dictionary.Keys.Count)
			{
				IEnumerator<FamilyInstance> enumerator = terminals.GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						FamilyInstance item = enumerator.Current;
						if (dictionary.Keys.FirstOrDefault((FamilyInstance x) => x == item) == null)
						{
							notConnTerminals.Add(item);
						}
					}
				}
			}
			return this.GetListDuctConnTerminals(dictionary, ref notConnTerminals);
		}

		private Dictionary<FamilyInstance, List<Duct>> GetListTerminalConnDuct(IList<Duct> listDuct, IList<FamilyInstance> terminals)
		{
			HYDuctConnect hyductConnect = new HYDuctConnect();
			int num = -1;
			Dictionary<FamilyInstance, List<Duct>> dictionary = new Dictionary<FamilyInstance, List<Duct>>();
			foreach (FamilyInstance familyInstance in terminals)
			{
				List<Duct> list = new List<Duct>();
				foreach (Duct duct in listDuct)
				{
					num = -1;
					string value = hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref num, true);
					bool flag = true;
					if (string.IsNullOrEmpty(value) && (num == 22 || num == 33))
					{
						flag = this.JudgeProjectPointOnDuct(familyInstance, duct);
					}
					if (string.IsNullOrEmpty(value) && flag)
					{
						list.Add(duct);
					}
				}
				dictionary.Add(familyInstance, list);
			}
			return dictionary;
		}

		private Dictionary<FamilyInstance, List<Duct>> GetMatchedDuctsAndTerminal(IList<Duct> listDuct, IList<FamilyInstance> terminals)
		{
			HYDuctConnect hyductConnect = new HYDuctConnect();
			int num = -1;
			Dictionary<FamilyInstance, List<Duct>> dictionary = new Dictionary<FamilyInstance, List<Duct>>();
			foreach (FamilyInstance familyInstance in terminals)
			{
				List<Duct> list = new List<Duct>();
				foreach (Duct duct in listDuct)
				{
					num = -1;
					if (string.IsNullOrEmpty(hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref num, false)) && (num == 22 || num == 33))
					{
						list.Add(duct);
					}
				}
				if (list.Count > 0)
				{
					dictionary.Add(familyInstance, list);
				}
			}
			return dictionary;
		}

		private bool Connectable(FamilyInstance terminal, Duct duct)
		{
			if (terminal == null || duct == null)
			{
				return false;
			}
			bool result = false;
			YJKRevitTools.GetElementConnector((Domain)1, terminal);
			return result;
		}

		private bool JudgeProjectPointOnDuct(FamilyInstance terminal, Duct duct)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			hyline.MakeUnBound();
			Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			XYZ project = hyline.GetProject(elementConnector.Origin);
			return hyline.IsPointOnLine(project);
		}

		private Dictionary<Duct, List<FamilyInstance>> GetListDuctConnTerminals(Dictionary<FamilyInstance, List<Duct>> fdDic, ref List<FamilyInstance> notConnTerminals)
		{
			Dictionary<Duct, List<FamilyInstance>> dictionary = new Dictionary<Duct, List<FamilyInstance>>();
			Duct duct = null;
			Func<Duct, bool> ss9__0 = null;
			foreach (KeyValuePair<FamilyInstance, List<Duct>> keyValuePair in fdDic)
			{
				FamilyInstance key = keyValuePair.Key;
				duct = this.GetConnDuct(key, keyValuePair.Value);
				if (duct == null)
				{
					notConnTerminals.Add(key);
				}
				else if (dictionary.Count < 1)
				{
					List<FamilyInstance> list = new List<FamilyInstance>();
					list.Add(key);
					dictionary.Add(duct, list);
				}
				else
				{
					IEnumerable<Duct> keys = dictionary.Keys;
					Func<Duct, bool> matchFun;
					if ((matchFun = ss9__0) == null)
					{
						matchFun = (ss9__0 = ((Duct d) => d.Id == duct.Id));
					}
					if (keys.Contains(matchFun))
					{
						dictionary[duct].Add(key);
					}
					else
					{
						List<FamilyInstance> list2 = new List<FamilyInstance>();
						list2.Add(key);
						dictionary.Add(duct, list2);
					}
				}
			}
			return dictionary;
		}

		private Duct GetConnDuct(FamilyInstance terminal, List<Duct> listDuct)
		{
			Duct result = null;
			if (listDuct == null || listDuct.Count < 1)
			{
				result = null;
			}
			else if (listDuct.Count == 1)
			{
				result = listDuct.First<Duct>();
			}
			else
			{
				double num = -1.0;
				for (int i = 0; i < listDuct.Count; i++)
				{
					if (i == 0)
					{
						num = this.GetDistanceTerminalToDuct(terminal, listDuct[i]);
						result = listDuct[i];
					}
					else
					{
						double distanceTerminalToDuct = this.GetDistanceTerminalToDuct(terminal, listDuct[i]);
						if (distanceTerminalToDuct != -1.0 && distanceTerminalToDuct < num)
						{
							num = this.GetDistanceTerminalToDuct(terminal, listDuct[i]);
							result = listDuct[i];
						}
					}
				}
			}
			return result;
		}

		private double GetDistanceTerminalToDuct(FamilyInstance terminal, Duct duct)
		{
			double result = -1.0;
			int num = -1;
			new HYDuctConnect().CheckTerminalBeCovered(duct, terminal, ref num, true);
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			hyline.MakeUnBound();
			XYZ origin = YJKRevitTools.GetElementConnector((Domain)1, terminal).Origin;
			if (num == 11)
			{
				result = hypiping.GetNearConnectorToPoint(origin).Origin.DistanceTo(origin);
			}
			else if (num == 22 || num == 33)
			{
				XYZ xyz = hyline.GetProject(origin);
				if (!hyline.IsPointOnLine(xyz))
				{
					xyz = hypiping.GetNearConnectorToPoint(xyz).Origin;
				}
				result = xyz.DistanceTo(origin);
			}
			return result;
		}

		public string SelectBatchConnElementSet(Selection sel, ref List<Duct> listDuct, ref List<FamilyInstance> terminals)
		{
			ISelectionFilter selectionFilter = new RectDuctAndTerminalsFilter();
			string text = "请框选若干风管(水平)和若干风口，其中至少包括一根风管及一个风口……";
			string text2 = "";
			try
			{
				IList<Element> listElem = sel.PickElementsByRectangle(selectionFilter, text);
				text2 = this.CheckConnElements(listElem, ref listDuct, ref terminals);
				if (!string.IsNullOrEmpty(text2))
				{
					return text2;
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				throw ex;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return text2;
		}

		public string SelectBatchConnElementSet(Selection sel, ref Duct duct, ref List<FamilyInstance> terminals, ref XYZ globalPoint, bool beCloser = false)
		{
			ISelectionFilter selectionFilter;
			string text;
			if (beCloser)
			{
				selectionFilter = new RectDuctAndTerminalsFilter();
				text = "请框选风管(水平)和风口，其中只能包括一根风管……";
			}
			else
			{
				selectionFilter = new HorizonDuctAndTerminalFilter();
				text = "请框选风管(水平)和风口，其中只能包括一根风管……";
			}
			string text2 = "";
			try
			{
				IList<Element> listElem = sel.PickElementsByRectangle(selectionFilter, text);
				text2 = this.CheckConnElements(listElem, ref duct, ref terminals);
				if (!string.IsNullOrEmpty(text2))
				{
					return text2;
				}
				if (!beCloser)
				{
					text = "请选择系统风管，根据选择点，与其相近的端点为系统的入口……";
					Reference reference = sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, new GivenDuctFilter(duct), text);
					globalPoint = reference.GlobalPoint;
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				throw ex;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return text2;
		}

		private string CheckTerminalPosition(Duct duct, List<FamilyInstance> terminals)
		{
			ConnectHelper connectHelper = new ConnectHelper();
			Connector connector = connectHelper.GetDuctConnector(duct)[0];
			int num = 0;
			foreach (Element elem in terminals)
			{
				Connector hyelementConnector = connectHelper.GetYJKElementConnector(elem);
				if (!hyelementConnector.CoordinateSystem.BasisZ.IsPerpendicularTo(connector.CoordinateSystem.BasisZ))
				{
					num = ConnectHelper.CheckPositionBetweenElement(hyelementConnector, connector);
				}
				if (num != 0)
				{
					break;
				}
			}
			return this.GetJudgeInformation(num);
		}

		private string GetJudgeInformation(int position)
		{
			string result = "";
			switch (position)
			{
			case 1:
				result = "不能完成连接，可能原因是，风口应该处于风管的下方。";
				break;
			case 2:
				result = "不能完成连接，可能原因是，风口应该处于风管的上方。";
				break;
			case 3:
				result = "不能完成连接，可能原因是，风口和风管上下位置不正确。";
				break;
			}
			return result;
		}

		private string CheckConnElements(IList<Element> listElem, ref Duct duct, ref List<FamilyInstance> termianls)
		{
			int num = 0;
			termianls = new List<FamilyInstance>();
			duct = null;
			foreach (Element element in listElem)
			{
				if (element is Duct)
				{
					if (num == 0)
					{
						duct = (element as Duct);
					}
					num++;
				}
				if (element is FamilyInstance)
				{
					termianls.Add(element as FamilyInstance);
				}
			}
			if (duct == null)
			{
				return "连接主风管不能为空，请重新选择。";
			}
			if (num > 1)
			{
				return "只能选择一根主风管，请重新选择。";
			}
			if (termianls.Count < 1)
			{
				return "没有选中风口，请重新选择。";
			}
			return "";
		}

		private string CheckConnElements(IList<Element> listElem, ref List<Duct> listDuct, ref List<FamilyInstance> termianls)
		{
			termianls = new List<FamilyInstance>();
			listDuct = new List<Duct>();
			foreach (Element element in listElem)
			{
				if (element is Duct)
				{
					listDuct.Add(element as Duct);
				}
				if (element is FamilyInstance)
				{
					termianls.Add(element as FamilyInstance);
				}
			}
			if (listDuct.Count < 1)
			{
				return "连接风管不能为空，请重新选择。";
			}
			if (termianls.Count < 1)
			{
				return "没有选中风口，请重新选择。";
			}
			return "";
		}

		public int GetDuctConnectType(Duct duct)
		{
			return duct.DuctType.GetParameter(BuiltInParameter.RBS_CURVETYPE_PREFERRED_BRANCH_PARAM).AsInteger();
		}
	}
}
